package com.khalil.kkadmin.ai.rag.knowledgeset.service.impl;

import com.alibaba.fastjson2.JSON;
import com.khalil.kkadmin.ai.rag.knowledgeset.entity.RagKnowledgeText;
import com.khalil.kkadmin.ai.rag.knowledgeset.service.RagKnowledgeTextService;
import com.khalil.kkadmin.ai.rag.knowledgeset.dto.RagKnowledgeDocDto;
import com.khalil.kkadmin.ai.rag.knowledgeset.entity.RagKnowledgeDoc;
import com.khalil.kkadmin.ai.rag.knowledgeset.repository.RagKnowledgeDocRepository;
import com.khalil.kkadmin.ai.rag.knowledgeset.service.RagKnowledgeDocService;
import com.khalil.kkadmin.common.util.CollectionUtils;
import com.khalil.kkadmin.infrastructure.BaseService;
import com.khalil.kkadmin.infrastructure.jpa.domain.EntityBase;
import com.khalil.kkadmin.system.dms.DmsDocument;
import com.khalil.kkadmin.system.dms.DmsDocumentService;
import com.khalil.kkadmin.system.dms.FileInfo;
import org.apache.commons.io.FilenameUtils;
import org.springframework.ai.document.Document;
import org.springframework.ai.reader.ExtractedTextFormatter;
import org.springframework.ai.reader.pdf.PagePdfDocumentReader;
import org.springframework.ai.reader.pdf.config.PdfDocumentReaderConfig;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.InputStreamResource;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
public class RagKnowledgeDocServiceImpl extends BaseService<RagKnowledgeDocRepository, RagKnowledgeDoc, Long> implements RagKnowledgeDocService {
    @Autowired
    private DmsDocumentService dmsDocumentService;

    private final List<String> UPLOAD_PATH = Arrays.asList("rag_knowledge_docs");

    public RagKnowledgeDocServiceImpl(RagKnowledgeDocRepository repository) {
        super(repository);
    }

    @Override
    protected RagKnowledgeDoc str2CreateEntity(String json) {
        return null;
    }

    @Override
    protected RagKnowledgeDoc str2UpdateEntity(String json) {
        return null;
    }

    @Override
    public List<RagKnowledgeDoc> list(String params) {
        return List.of();
    }

    @Override
    public List<RagKnowledgeDocDto> upload(Long knowledgeSetId, List<MultipartFile> files) {
        List<RagKnowledgeDocDto> documentInfoList = new ArrayList<>();
        files.forEach(file -> {
            String originalFilename = file.getOriginalFilename();
            String extension = FilenameUtils.getExtension(originalFilename);
            String contentType = file.getContentType();
            InputStream inputStream = null;
            try {
                inputStream = file.getInputStream();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
            long fileSize = file.getSize();
            FileInfo fileInfo = FileInfo.builder()
                    .originalFilename(originalFilename)
                    .contentType(contentType)
                    .size(fileSize)
                    .extension(extension)
                    .inputStream(inputStream).build();
            DmsDocument dmsDocument = dmsDocumentService.upload(UPLOAD_PATH, fileInfo);

            RagKnowledgeDoc knowledgeDoc = new RagKnowledgeDoc();
            knowledgeDoc.setDocumentId(dmsDocument.getId());
            knowledgeDoc.setKnowledgeSetId(knowledgeSetId);
            knowledgeDoc.setTextExtractStatus(RagKnowledgeDoc.TEXT_EXTRACT_STATUS_NOT_START);
            repository.save(knowledgeDoc);

            RagKnowledgeDocDto documentDto = new RagKnowledgeDocDto();
            documentDto.setId(knowledgeDoc.getId());
            documentDto.setDocumentId(dmsDocument.getId());
            documentDto.setKnowledgeSetId(knowledgeSetId);
            BeanUtils.copyProperties(dmsDocument, documentDto);
            documentInfoList.add(documentDto);
        });
        return documentInfoList;
    }

    @Override
    public RagKnowledgeDocDto getKnowledgeDoc(Long id) {
        Optional<RagKnowledgeDoc> knowledgeDocOptional = repository.findById(id);
        if (knowledgeDocOptional.isEmpty()) {
            return null;
        }
        RagKnowledgeDoc knowledgeDoc = knowledgeDocOptional.get();
        DmsDocument dmsDocument = dmsDocumentService.findById(knowledgeDoc.getDocumentId());
        if (dmsDocument == null) {
            return null;
        }
        return buildRagDmsDocumentDto(knowledgeDoc, dmsDocument);
    }

    @Override
    public List<RagKnowledgeDocDto> listByKnowledgeSetId(Long dirId) {
        List<RagKnowledgeDoc> knowledgeDocList = repository.findByKnowledgeSetId(dirId);
        if (CollectionUtils.isEmpty(knowledgeDocList)) {
            return Collections.emptyList();
        }
        List<Long> documentIdList = knowledgeDocList.stream().map(RagKnowledgeDoc::getDocumentId).toList();
        List<DmsDocument> dmsDocumentList = dmsDocumentService.findByIdList(documentIdList);
        Map<Long, DmsDocument> documentMap = dmsDocumentList.stream().collect(Collectors.toMap(EntityBase::getId, Function.identity()));

        return knowledgeDocList.stream().map(knowledgeDoc -> {
            DmsDocument dmsDocument = documentMap.get(knowledgeDoc.getDocumentId());

            return buildRagDmsDocumentDto(knowledgeDoc, dmsDocument);
        }).collect(Collectors.toList());
    }

    private RagKnowledgeDocDto buildRagDmsDocumentDto(RagKnowledgeDoc knowledgeDoc, DmsDocument dmsDocument) {
        RagKnowledgeDocDto documentDto = new RagKnowledgeDocDto();
        BeanUtils.copyProperties(dmsDocument, documentDto);
        documentDto.setId(knowledgeDoc.getId());
        documentDto.setDocumentId(knowledgeDoc.getDocumentId());
        documentDto.setKnowledgeSetId(knowledgeDoc.getKnowledgeSetId());
        documentDto.setTextExtractStatus(knowledgeDoc.getTextExtractStatus());
        documentDto.setCreatedAt(knowledgeDoc.getCreatedAt());
        return documentDto;
    }

    @Transactional
    @Override
    public void deleteByIdList(List<Long> idList) {
        for (Long id : idList) {
            deleteById(id);
        }
    }

    @Transactional
    @Override
    public void deleteById(Long id) {
        // 删除文件
        RagKnowledgeDoc knowledgeDoc = repository.findById(id).orElse(null);
        if (knowledgeDoc != null) {
            dmsDocumentService.deleteById(knowledgeDoc.getDocumentId());
        }
        // 删除数据
        repository.deleteById(id);
    }
}
